home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / other / jikes / src / diagnose.cpp < prev    next >
C/C++ Source or Header  |  1999-05-14  |  97KB  |  2,500 lines

  1. // $Id: diagnose.cpp,v 1.5 1999/02/24 19:40:14 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <assert.h>
  12. #include <iostream.h>
  13. #include "diagnose.h"
  14. #include "control.h"
  15. #include "semantic.h"
  16. #include "unicode.h"
  17. #include "case.h"
  18. #include "spell.h"
  19.  
  20. void DiagnoseParser::ReallocateStacks()
  21. {
  22.     int old_stack_length = stack_length;
  23.  
  24.     stack_length += STACK_INCREMENT;
  25.     assert(stack_length <= SHRT_MAX);
  26.  
  27.     int *old_stack = stack; 
  28.     stack = (int *) memmove(new int[stack_length], stack, old_stack_length * sizeof(int));
  29.     delete [] old_stack;
  30.  
  31.     Location *old_location_stack = location_stack; 
  32.     location_stack = (Location *) memmove(new Location[stack_length], location_stack, old_stack_length * sizeof(Location));
  33.     delete [] old_location_stack;
  34.  
  35.     Ast **old_parse_stack = parse_stack;
  36.     parse_stack = (Ast **) memmove(new Ast *[stack_length], parse_stack, old_stack_length * sizeof(Ast *));
  37.     delete [] old_parse_stack;
  38.  
  39.     int *old_temp_stack = temp_stack;
  40.     temp_stack = (int *) memmove(new int[stack_length], temp_stack, old_stack_length * sizeof(int));
  41.     delete [] old_temp_stack;
  42.  
  43.     int *old_next_stack = next_stack;
  44.     next_stack = (int *) memmove(new int[stack_length], next_stack, old_stack_length * sizeof(int));
  45.     delete [] old_next_stack;
  46.  
  47.     int *old_prev_stack = prev_stack;
  48.     prev_stack = (int *) memmove(new int[stack_length], prev_stack, old_stack_length * sizeof(int));
  49.     delete [] old_prev_stack;
  50.  
  51.     int *old_scope_index = scope_index;
  52.     scope_index = (int *) memmove(new int[stack_length], scope_index, old_stack_length * sizeof(int));
  53.     delete [] old_scope_index;
  54.  
  55.     int *old_scope_position = scope_position;
  56.     scope_position = (int *) memmove(new int[stack_length], scope_position, old_stack_length * sizeof(int));
  57.     delete [] old_scope_position;
  58.  
  59.     return;
  60. }
  61.  
  62.  
  63. void DiagnoseParser::DiagnoseParse()
  64. {
  65.     lex_stream -> Reset();
  66.  
  67.     TokenObject curtok = lex_stream -> Gettoken();
  68.  
  69.     int prev_pos,
  70.         pos,
  71.         next_pos,
  72.         i,
  73.         tok,
  74.         lhs_symbol,
  75.         act = START_STATE,
  76.         current_kind = lex_stream -> Kind(curtok);
  77.  
  78.     ReallocateStacks();
  79.  
  80. /*****************************************************************/
  81. /* Start parsing.                                                */
  82. /*****************************************************************/
  83.     state_stack_top = 0;
  84.     stack[state_stack_top] = act;
  85.  
  86.     tok = lex_stream -> Kind(curtok);
  87.     location_stack[state_stack_top] = Loc(curtok);
  88.  
  89.     //
  90.     // Process a terminal
  91.     // 
  92.     do
  93.     {
  94.         /*************************************************************/
  95.         /* Synchronize state stacks and update the location stack.   */
  96.         /*************************************************************/
  97.         prev_pos = -1;
  98.         prev_stack_top = -1;
  99.  
  100.         next_pos = -1;
  101.         next_stack_top = -1;
  102.  
  103.         pos = state_stack_top;
  104.         temp_stack_top = state_stack_top - 1;
  105.         for (i = 0; i <= state_stack_top; i++)
  106.             temp_stack[i] = stack[i];
  107.  
  108.         act = t_action(act, tok, lex_stream);
  109. /*****************************************************************/
  110. /* When a reduce action is encountered, we compute all REDUCE    */
  111. /* and associated goto actions induced by the current token.     */
  112. /* Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is  */
  113. /* computed...                                                   */
  114. /*****************************************************************/
  115.         while (act <= NUM_RULES)
  116.         {
  117.             do
  118.             {
  119.                 temp_stack_top -= (rhs[act]-1);
  120.                 //
  121.                 // if no error detected?
  122.                 //     semantic_action(act);
  123.                 //
  124.                 act = nt_action(temp_stack[temp_stack_top], lhs[act]);
  125.             } while(act <= NUM_RULES);
  126.             /*************************************************/
  127.             /* ... Update the maximum useful position of the */
  128.             /* (STATE_)STACK, push goto state into stack, and*/
  129.             /* compute next action on current symbol ...     */
  130.             /*************************************************/
  131.             if (temp_stack_top + 1 >= stack_length)
  132.                 ReallocateStacks();
  133.             pos = Min(pos, temp_stack_top);
  134.             temp_stack[temp_stack_top + 1] = act;
  135.             act = t_action(act, tok, lex_stream);
  136.         }
  137.  
  138. /*****************************************************************/
  139. /* At this point, we have a shift, shift-reduce, accept or error */
  140. /* action.  STACK contains the configuration of the state stack  */
  141. /* prior to executing any action on curtok. next_stack contains  */
  142. /* the configuration of the state stack after executing all      */
  143. /* reduce actions induced by curtok.  The variable pos indicates */
  144. /* the highest position in STACK that is still useful after the  */
  145. /* reductions are executed.                                      */
  146. /*****************************************************************/
  147.         while(act > ERROR_ACTION ||       /* SHIFT-REDUCE action */
  148.               act < ACCEPT_ACTION)               /* SHIFT action */
  149.         {
  150.             next_stack_top = temp_stack_top + 1;
  151.             for (i = next_pos + 1; i <= next_stack_top; i++)
  152.                 next_stack[i] = temp_stack[i];
  153.  
  154.             for (i = pos + 1; i <= next_stack_top; i++)
  155.                 location_stack[i] = location_stack[state_stack_top];
  156.  
  157.             /*****************************************************/
  158.             /* If we have a shift-reduce, process it as well as  */
  159.             /* the goto-reduce actions that follow it.           */
  160.             /*****************************************************/
  161.             if (act > ERROR_ACTION)
  162.             {
  163.                 act -= ERROR_ACTION;
  164.                 do
  165.                 {
  166.                     next_stack_top -= (rhs[act]-1);
  167.                     //
  168.                     // if no error detected?
  169.                     //     semantic_action(act);
  170.                     //
  171.                     act = nt_action(next_stack[next_stack_top], lhs[act]);
  172.                 } while(act <= NUM_RULES);
  173.                 pos = Min(pos, next_stack_top);
  174.             }
  175.  
  176.             if (next_stack_top + 1 >= stack_length)
  177.                 ReallocateStacks();
  178.  
  179.             temp_stack_top = next_stack_top;
  180.             next_stack[++next_stack_top] = act;
  181.             next_pos = next_stack_top;
  182.  
  183.             /********************************************************/
  184.             /* Simulate the parser through the next token without   */
  185.             /* destroying STACK or next_stack.                      */
  186.             /********************************************************/
  187.             curtok = lex_stream -> Gettoken();
  188.             tok = lex_stream -> Kind(curtok);
  189.             act = t_action(act, tok, lex_stream);
  190.             while(act <= NUM_RULES)
  191.             {
  192.                 /*************************************************/
  193.                 /* ... Process all goto-reduce actions following */
  194.                 /* reduction, until a goto action is computed ...*/
  195.                 /*************************************************/
  196.                 do
  197.                 {
  198.                     lhs_symbol = lhs[act];
  199.                     temp_stack_top -= (rhs[act]-1);
  200.                     //
  201.                     // if no error detected?
  202.                     //     semantic_action(act);
  203.                     //
  204.                     act = (temp_stack_top > next_pos
  205.                                ? temp_stack[temp_stack_top]
  206.                                : next_stack[temp_stack_top]);
  207.                     act = nt_action(act, lhs_symbol);
  208.                 }   while(act <= NUM_RULES);
  209.  
  210.                 /*************************************************/
  211.                 /* ... Update the maximum useful position of the */
  212.                 /* (STATE_)STACK, push GOTO state into stack, and*/
  213.                 /* compute next action on current symbol ...     */
  214.                 /*************************************************/
  215.                 if (temp_stack_top + 1 >= stack_length)
  216.                     ReallocateStacks();
  217.  
  218.                 next_pos = Min(next_pos, temp_stack_top);
  219.                 temp_stack[temp_stack_top + 1] = act;
  220.                 act = t_action(act, tok, lex_stream);
  221.             }
  222.  
  223.             /*****************************************************/
  224.             /* No error was detected, Read next token into       */
  225.             /* PREVTOK element, advance CURTOK pointer and       */
  226.             /* update stacks.                                    */
  227.             /*****************************************************/
  228.             if (act != ERROR_ACTION)
  229.             {
  230.                 prev_stack_top = state_stack_top;
  231.                 for (i = prev_pos + 1; i <= prev_stack_top; i++)
  232.                     prev_stack[i] = stack[i];
  233.                 prev_pos = pos;
  234.  
  235.                 state_stack_top = next_stack_top;
  236.                 for (i = pos + 1; i <= state_stack_top; i++)
  237.                     stack[i] = next_stack[i];
  238.                 location_stack[state_stack_top] = Loc(curtok);
  239.                 pos = next_pos;
  240.             }
  241.         }
  242.  
  243.         /*********************************************************/
  244.         /* At this stage, either we have an ACCEPT or an ERROR   */
  245.         /* action.                                               */
  246.         /*********************************************************/
  247.         if (act == ERROR_ACTION)
  248.         {
  249.             //
  250.             // An error was detected.
  251.             //
  252.  
  253.             RepairCandidate candidate = ErrorRecovery(curtok);
  254.  
  255.             act = stack[state_stack_top];
  256.  
  257. /*****************************************************************/
  258. /* If the recovery was successful on a nonterminal candidate,    */
  259. /* parse through that candidate and "read" the next token.       */
  260. /*****************************************************************/
  261.             if (!candidate.symbol)
  262.                 break;
  263.             else if (candidate.symbol > NT_OFFSET)
  264.             {
  265.                 lhs_symbol = candidate.symbol - NT_OFFSET;
  266.                 act = nt_action(act, lhs_symbol);
  267.                 while(act <= NUM_RULES)
  268.                 {
  269.                     state_stack_top -= (rhs[act]-1);
  270.                     act = nt_action(stack[state_stack_top], lhs[act]);
  271.                 }
  272.                 stack[++state_stack_top] = act;
  273.                 curtok = lex_stream -> Gettoken();
  274.                 tok = lex_stream -> Kind(curtok);
  275.                 location_stack[state_stack_top] = Loc(curtok);
  276.             }
  277.             else
  278.             {
  279.                 tok = candidate.symbol;
  280.                 location_stack[state_stack_top] = candidate.location;
  281.             }
  282.         }
  283.     } while (act != ACCEPT_ACTION);
  284.  
  285.     error.PrintMessages();
  286.  
  287.     return;
  288. }
  289.  
  290.  
  291. /*****************************************************************/
  292. /*  This routine is invoked when an error is encountered.  It    */
  293. /* tries to diagnose the error and recover from it.  If it is    */
  294. /* successful, the state stack, the current token and the buffer */
  295. /* are readjusted; i.e., after a successful recovery,            */
  296. /* state_stack_top points to the location in the state stack     */
  297. /* that contains the state on which to recover; curtok           */
  298. /* identifies the symbol on which to recover.                    */
  299. /*                                                               */
  300. /* Up to three configurations may be available when this routine */
  301. /* is invoked. PREV_STACK may contain the sequence of states     */
  302. /* preceding any action on prevtok, STACK always contains the    */
  303. /* sequence of states preceding any action on curtok, and        */
  304. /* NEXT_STACK may contain the sequence of states preceding any   */
  305. /* action on the successor of curtok.                            */
  306. /*****************************************************************/
  307. RepairCandidate DiagnoseParser::ErrorRecovery(TokenObject error_token)
  308. {
  309.     TokenObject prevtok = lex_stream -> Previous(error_token);
  310.  
  311.     RepairCandidate candidate;
  312.  
  313. /*****************************************************************/
  314. /* Try primary phase recoveries. If not successful, try secondary*/
  315. /* phase recoveries.  If not successful and we are at end of the */
  316. /* file, we issue the end-of-file error and quit. Otherwise, ... */
  317. /*****************************************************************/
  318.     candidate = PrimaryPhase(error_token);
  319.     if (candidate.symbol)
  320.         return candidate;
  321.  
  322.     candidate = SecondaryPhase(error_token);
  323.     if (candidate.symbol)
  324.         return candidate;
  325.  
  326.     if (lex_stream -> Kind(error_token) == EOFT_SYMBOL)
  327.     {
  328.         error.Report(0, EOF_CODE, terminal_index[EOFT_SYMBOL],
  329.                                   Loc(prevtok), prevtok);
  330.         candidate.symbol = 0;
  331.         candidate.location = Loc(error_token);
  332.         return candidate;
  333.     }
  334.  
  335. /*****************************************************************/
  336. /* At this point, primary and (initial attempt at) secondary     */
  337. /* recovery did not work.  We will now get into "panic mode" and */
  338. /* keep trying secondary phase recoveries until we either find   */
  339. /* a successful recovery or have consumed the remaining input    */
  340. /* tokens.                                                       */
  341. /*****************************************************************/
  342.     while(lex_stream -> Kind(buffer[BUFF_UBOUND]) != EOFT_SYMBOL)
  343.     {
  344.         candidate = SecondaryPhase(buffer[MAX_DISTANCE - MIN_DISTANCE + 2]);
  345.         if (candidate.symbol)
  346.             return candidate;
  347.     }
  348.  
  349. /*****************************************************************/
  350. /* We reached the end of the file while panicking. Delete all    */
  351. /* remaining tokens in the input.                                */
  352. /*****************************************************************/
  353.     int i;
  354.     for (i = BUFF_UBOUND; lex_stream -> Kind(buffer[i]) == EOFT_SYMBOL; i--)
  355.         ;
  356.  
  357.     error.Report(0, DELETION_CODE, terminal_index[lex_stream -> Kind(prevtok)],
  358.                                    Loc(error_token), buffer[i]);
  359.  
  360.     candidate.symbol = 0;
  361.     candidate.location = Loc(buffer[i]);
  362.  
  363.     return candidate;
  364. }
  365.  
  366.  
  367. /*****************************************************************/
  368. /* This function tries primary and scope recovery on each        */
  369. /* available configuration.  If a successful recovery is found   */
  370. /* and no secondary phase recovery can do better, a diagnosis is */
  371. /* issued, the configuration is updated and the function returns */
  372. /* "true".  Otherwise, it returns "false".                       */
  373. /*****************************************************************/
  374. RepairCandidate DiagnoseParser::PrimaryPhase(TokenObject error_token)
  375. {
  376.     PrimaryRepairInfo repair,
  377.                       new_repair;
  378.  
  379.     RepairCandidate candidate;
  380.  
  381.     repair.distance = 0;
  382.     repair.misspell_index = 0;
  383.     repair.code = 0;
  384.  
  385.     candidate.symbol = 0;
  386.  
  387. /*****************************************************************/
  388. /* Initialize the buffer.                                        */
  389. /*****************************************************************/
  390.     int i = (next_stack_top >= 0 ? 3 : 2);
  391.     buffer[i] = error_token;
  392.  
  393.     int k;
  394.     for (k = i; k > 0; k--)
  395.         buffer[k - 1] = lex_stream -> Previous(buffer[k]);
  396.  
  397.     for (k = i + 1; k < BUFF_SIZE; k++)
  398.         buffer[k] = lex_stream -> Next(buffer[k - 1]);
  399.  
  400. /*****************************************************************/
  401. /* If NEXT_STACK_TOP > 0 then the parse was successful on CURTOK */
  402. /* and the error was detected on the successor of CURTOK. In     */
  403. /* that case, first check whether or not primary recovery is     */
  404. /* possible on next_stack ...                                    */
  405. /*****************************************************************/
  406.     if (next_stack_top >= 0)
  407.     {
  408.         repair.buffer_position = 3;
  409.         repair = CheckPrimaryDistance(next_stack, next_stack_top, repair);
  410.     }
  411.  
  412. /*****************************************************************/
  413. /* ... Next, try primary recovery on the current token...        */
  414. /*****************************************************************/
  415.     new_repair = repair;
  416.  
  417.     new_repair.buffer_position = 2;
  418.     new_repair = CheckPrimaryDistance(stack, state_stack_top, new_repair);
  419.     if (new_repair.distance > repair.distance ||
  420.         new_repair.misspell_index > repair.misspell_index)
  421.         repair = new_repair;
  422.  
  423. /*****************************************************************/
  424. /* Finally, if prev_stack_top >= 0 then try primary recovery on  */
  425. /* the prev_stack configuration.                                 */
  426. /*****************************************************************/
  427.     if (prev_stack_top >= 0)
  428.     {
  429.         new_repair = repair;
  430.         new_repair.buffer_position = 1;
  431.         new_repair = CheckPrimaryDistance(prev_stack,
  432.                                           prev_stack_top, new_repair);
  433.         if (new_repair.distance > repair.distance ||
  434.             new_repair.misspell_index > repair.misspell_index)
  435.             repair = new_repair;
  436.     }
  437.  
  438. /*****************************************************************/
  439. /* Before accepting the best primary phase recovery obtained,    */
  440. /* ensure that we cannot do better with a similar secondary      */
  441. /* phase recovery.                                               */
  442. /*****************************************************************/
  443.     if (next_stack_top >= 0)             /* next_stack available */
  444.     {
  445.         if (SecondaryCheck(next_stack,next_stack_top,3,repair.distance))
  446.               return candidate;
  447.     }
  448.     else if (SecondaryCheck(stack, state_stack_top, 2, repair.distance))
  449.              return candidate;
  450.  
  451. /*****************************************************************/
  452. /* First, adjust distance if the recovery is on the error token; */
  453. /* it is important that the adjustment be made here and not at   */
  454. /* each primary trial to prevent the distance tests from being   */
  455. /* biased in favor of deferred recoveries which have access to   */
  456. /* more input tokens...                                          */
  457. /*****************************************************************/
  458.     repair.distance = repair.distance - repair.buffer_position + 1;
  459.  
  460. /*****************************************************************/
  461. /* ...Next, adjust the distance if the recovery is a deletion or */
  462. /* (some form of) substitution...                                */
  463. /*****************************************************************/
  464.     if (repair.code == INVALID_CODE      ||
  465.         repair.code == DELETION_CODE     ||
  466.         repair.code == SUBSTITUTION_CODE ||
  467.         repair.code == MERGE_CODE)
  468.          repair.distance--;
  469.  
  470. /*****************************************************************/
  471. /* ... After adjustment, check if the most successful primary    */
  472. /* recovery can be applied.  If not, continue with more radical  */
  473. /* recoveries...                                                 */
  474. /*****************************************************************/
  475.     if (repair.distance < MIN_DISTANCE)
  476.         return candidate;
  477.  
  478. /*****************************************************************/
  479. /* When processing an insertion error, if the token preceeding   */
  480. /* the error token is not available, we change the repair code   */
  481. /* into a BEFORE_CODE to instruct the reporting routine that it  */
  482. /* indicates that the repair symbol should be inserted before    */
  483. /* the error token.                                              */
  484. /*****************************************************************/
  485.     if (repair.code == INSERTION_CODE)
  486.     {
  487.         if (! lex_stream -> Kind(buffer[repair.buffer_position - 1]))
  488.             repair.code = BEFORE_CODE;
  489.     }
  490.  
  491. /*****************************************************************/
  492. /* Select the proper sequence of states on which to recover,     */
  493. /* update stack accordingly and call diagnostic routine.         */
  494. /*****************************************************************/
  495.     if (repair.buffer_position == 1)
  496.     {
  497.         state_stack_top = prev_stack_top;
  498.         for (i = 0; i <= state_stack_top; i++)
  499.             stack[i] = prev_stack[i];
  500.     }
  501.     else if (next_stack_top >= 0 && repair.buffer_position >= 3)
  502.     {
  503.         state_stack_top = next_stack_top;
  504.         for (i = 0; i <= state_stack_top; i++)
  505.             stack[i] = next_stack[i];
  506.         location_stack[state_stack_top] = Loc(buffer[3]);
  507.     }
  508.  
  509.     return PrimaryDiagnosis(repair);
  510. }
  511.  
  512.  
  513. /*****************************************************************/
  514. /*     This function checks whether or not a given state has a   */
  515. /* candidate, whose string representaion is a merging of the two */
  516. /* tokens at positions buffer_position and buffer_position+1 in  */
  517. /* the buffer.  If so, it returns the candidate in question;     */
  518. /* otherwise it returns 0.                                       */
  519. /*****************************************************************/
  520. bool DiagnoseParser::MergeCandidate(int state, int buffer_position)
  521. {
  522.     int i,
  523.         k,
  524.         len,
  525.         len1,
  526.         len2;
  527.  
  528.     const wchar_t *p1,
  529.                   *p2;
  530.  
  531.     wchar_t str[MAX_TERM_LENGTH + 1];
  532.  
  533.     len1 = 0;
  534.     for (p1 = lex_stream -> Name(buffer[buffer_position]); *p1; p1++)
  535.         len1++;
  536.     len2 = 0;
  537.     for (p2 = lex_stream -> Name(buffer[buffer_position + 1]); *p2; p2++)
  538.         len2++;
  539.     len  = len1 + len2;
  540.  
  541.     p1 = lex_stream -> Name(buffer[buffer_position]);
  542.     p2 = lex_stream -> Name(buffer[buffer_position + 1]);
  543.  
  544.     if (len <= MAX_TERM_LENGTH)
  545.     {
  546.         wchar_t *p0;
  547.  
  548.         p0 = &str[0];
  549.         for (i = 0; i < len1; i++)
  550.             *(p0++) = p1[i];
  551.         for (i = 0; i < len2; i++)
  552.             *(p0++) = p2[i];
  553.         *p0 = U_NULL;
  554.  
  555.         for (i = asi(state); asr[i] != 0; i++)
  556.         {
  557.             k = terminal_index[asr[i]];
  558.             if (len == name_length[k])
  559.             {
  560.                 const char *p3 = &string_buffer[name_start[k]];
  561.  
  562.                 p0 = &str[0];
  563.                 while (*p0 != U_NULL)
  564.                 {
  565.                     wchar_t c = *(p3++);
  566. #ifdef EBCDIC
  567.                     c = Code::ToASCII(c);
  568. #endif
  569.  
  570.                     if (Case::ToAsciiLower(*p0) != Case::ToAsciiLower(c))
  571.                         break;
  572.                     p0++;
  573.                 }
  574.                 if (*p0 == U_NULL)
  575.                     return asr[i];
  576.             }
  577.         }
  578.     }
  579.  
  580.     return 0;
  581. }
  582.  
  583.  
  584. /*****************************************************************/
  585. /* This procedure takes as arguments a parsing configuration     */
  586. /* consisting of a state stack (stack and stack_top) and a fixed */
  587. /* number of input tokens (starting at buffer_position) in the   */
  588. /* input BUFFER; and some reference arguments: repair_code,      */
  589. /* distance, misspell_index, candidate, and stack_position       */
  590. /* which it sets based on the best possible recovery that it     */
  591. /* finds in the given configuration.  The effectiveness of a     */
  592. /* a repair is judged based on two criteria:                     */
  593. /*                                                               */
  594. /*   1) the number of tokens that can be parsed after the repair */
  595. /*      is applied: distance.                                    */
  596. /*   2) how close to perfection is the candidate that is chosen: */
  597. /*      misspell_index.                                          */
  598. /* When this procedure is entered, distance, misspell_index and  */
  599. /* repair_code are assumed to be initialized.                    */
  600. /*****************************************************************/
  601. PrimaryRepairInfo DiagnoseParser::CheckPrimaryDistance
  602.        (int stck[], int stack_top, PrimaryRepairInfo repair)
  603. {
  604.     PrimaryRepairInfo scope_repair;
  605.     int i,
  606.         j,
  607.         k,
  608.         next_state,
  609.         max_pos,
  610.         act,
  611.         root,
  612.         symbol,
  613.         tok;
  614.  
  615. /*****************************************************************/
  616. /*  First, try scope and manual recovery.                        */
  617. /*****************************************************************/
  618. #if defined(SCOPE_REPAIR)
  619.     scope_repair = ScopeTrial(stck, stack_top, repair);
  620.     if (scope_repair.distance > repair.distance)
  621.         repair = scope_repair;
  622. #endif
  623.  
  624. /*****************************************************************/
  625. /*  Next, try merging the error token with its successor.        */
  626. /*****************************************************************/
  627.     symbol = MergeCandidate(stck[stack_top], repair.buffer_position);
  628.     if (symbol != 0)
  629.     {
  630.         j = ParseCheck(stck, stack_top,
  631.                        symbol, repair.buffer_position+2);
  632.         if ((j > repair.distance) ||
  633.             (j == repair.distance && repair.misspell_index < 10))
  634.         {
  635.             repair.misspell_index = 10;
  636.             repair.symbol = symbol;
  637.             repair.distance = j;
  638.             repair.code = MERGE_CODE;
  639.         }
  640.     }
  641.  
  642. /*****************************************************************/
  643. /* Next, try deletion of the error token.                        */
  644. /*****************************************************************/
  645.     j = ParseCheck(stck, stack_top,
  646.                    lex_stream -> Kind(buffer[repair.buffer_position+1]),
  647.                    repair.buffer_position+2);
  648.     if (lex_stream -> Kind(buffer[repair.buffer_position]) == EOLT_SYMBOL &&
  649.         lex_stream -> AfterEol(buffer[repair.buffer_position+1]))
  650.          k = 10;
  651.     else k = 0;
  652.     if (j > repair.distance || (j == repair.distance && k > repair.misspell_index))
  653.     {
  654.         repair.misspell_index = k;
  655.         repair.code = DELETION_CODE;
  656.         repair.distance = j;
  657.     }
  658.  
  659. /*****************************************************************/
  660. /* Update the error configuration by simulating all reduce and   */
  661. /* goto actions induced by the error token. Then assign the top  */
  662. /* most state of the new configuration to next_state.            */
  663. /*****************************************************************/
  664.     next_state = stck[stack_top];
  665.     max_pos = stack_top;
  666.     temp_stack_top = stack_top - 1;
  667.  
  668.     tok = lex_stream -> Kind(buffer[repair.buffer_position]);
  669.     lex_stream -> Reset(buffer[repair.buffer_position + 1]);
  670.     act = t_action(next_state, tok, lex_stream);
  671.     while(act <= NUM_RULES)
  672.     {
  673.         do
  674.         {
  675.             temp_stack_top -= (rhs[act]-1);
  676.             symbol = lhs[act];
  677.             act = (temp_stack_top > max_pos
  678.                                   ? temp_stack[temp_stack_top]
  679.                                   : stck[temp_stack_top]);
  680.             act = nt_action(act, symbol);
  681.         }   while(act <= NUM_RULES);
  682.         max_pos = Min(max_pos, temp_stack_top);
  683.         temp_stack[temp_stack_top + 1] = act;
  684.         next_state = act;
  685.         act = t_action(next_state, tok, lex_stream);
  686.     }
  687.  
  688. /*****************************************************************/
  689. /*  Next, place the list of candidates in proper order.          */
  690. /*****************************************************************/
  691.     root = 0;
  692.     for (i = asi(next_state); asr[i] != 0; i++)
  693.     {
  694.         symbol = asr[i];
  695.         if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL)
  696.         {
  697.             if (root == 0)
  698.                 list[symbol] = symbol;
  699.             else
  700.             {
  701.                 list[symbol] = list[root];
  702.                 list[root] = symbol;
  703.             }
  704.             root = symbol;
  705.         }
  706.     }
  707.  
  708.     if (stck[stack_top] != next_state)
  709.     {
  710.         for (i = asi(stck[stack_top]); asr[i] != 0; i++)
  711.         {
  712.             symbol = asr[i];
  713.             if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL &&
  714.                                          list[symbol] == 0)
  715.             {
  716.                 if (root == 0)
  717.                     list[symbol] = symbol;
  718.                 else
  719.                 {
  720.                     list[symbol] = list[root];
  721.                     list[root] = symbol;
  722.                 }
  723.                 root = symbol;
  724.             }
  725.         }
  726.     }
  727.  
  728.     i = list[root];
  729.     list[root] = 0;
  730.     root = i;
  731.  
  732. /*****************************************************************/
  733. /*  Next, try insertion for each possible candidate available in */
  734. /* the current state, except EOFT and ERROR_SYMBOL.              */
  735. /*****************************************************************/
  736.     symbol = root;
  737.     while(symbol != 0)
  738.     {
  739.         if (symbol == EOLT_SYMBOL &&
  740.             lex_stream -> AfterEol(buffer[repair.buffer_position]))
  741.              k = 10;
  742.         else k = 0;
  743.         j = ParseCheck(stck, stack_top,
  744.                        symbol, repair.buffer_position);
  745.         if (j > repair.distance)
  746.         {
  747.             repair.misspell_index = k;
  748.             repair.distance = j;
  749.             repair.symbol = symbol;
  750.             repair.code = INSERTION_CODE;
  751.         }
  752.         else if (j == repair.distance && k > repair.misspell_index)
  753.         {
  754.             repair.misspell_index = k;
  755.             repair.distance = j;
  756.             repair.symbol = symbol;
  757.             repair.code = INSERTION_CODE;
  758.         }
  759.  
  760.         symbol = list[symbol];
  761.     }
  762.  
  763. /*****************************************************************/
  764. /*  Next, Try substitution for each possible candidate available */
  765. /* in the current state, except EOFT and ERROR_SYMBOL.           */
  766. /*****************************************************************/
  767.     symbol = root;
  768.     while(symbol != 0)
  769.     {
  770.         if (symbol == EOLT_SYMBOL &&
  771.             lex_stream -> AfterEol(buffer[repair.buffer_position+1]))
  772.              k = 10;
  773.         else k = Misspell(symbol, buffer[repair.buffer_position]);
  774.         j = ParseCheck(stck, stack_top,
  775.                        symbol, repair.buffer_position+1);
  776.         if (j > repair.distance)
  777.         {
  778.             repair.misspell_index = k;
  779.             repair.distance = j;
  780.             repair.symbol = symbol;
  781.             repair.code = SUBSTITUTION_CODE;
  782.         }
  783.         else if (j == repair.distance && k > repair.misspell_index)
  784.         {
  785.             repair.misspell_index = k;
  786.             repair.symbol = symbol;
  787.             repair.code = SUBSTITUTION_CODE;
  788.         }
  789.         i = symbol;
  790.         symbol = list[symbol];
  791.         list[i] = 0;                             /* reset element */
  792.     }
  793.  
  794.  
  795. /*****************************************************************/
  796. /* Next, we try to insert a nonterminal candidate in front of the*/
  797. /* error token, or substituting a nonterminal candidate for the  */
  798. /* error token. Precedence is given to insertion.                */
  799. /*****************************************************************/
  800.      for (i = nasi(stck[stack_top]); nasr[i] != 0; i++)
  801.      {
  802.          symbol = nasr[i] + NT_OFFSET;
  803.          j = ParseCheck(stck, stack_top,
  804.                         symbol, repair.buffer_position+1);
  805.          if (j > repair.distance)
  806.          {
  807.              repair.misspell_index = 0;
  808.              repair.distance = j;
  809.              repair.symbol = symbol;
  810.              repair.code = INVALID_CODE;
  811.          }
  812.  
  813.          j = ParseCheck(stck, stack_top, symbol, repair.buffer_position);
  814.          if ((j > repair.distance) ||
  815.              (j == repair.distance && repair.code == INVALID_CODE))
  816.          {
  817.              repair.misspell_index = 0;
  818.              repair.distance = j;
  819.              repair.symbol = symbol;
  820.              repair.code = INSERTION_CODE;
  821.          }
  822.      }
  823.  
  824.     return repair;
  825. }
  826.  
  827.  
  828. /*****************************************************************/
  829. /* This procedure is invoked to issue a diagnostic message and   */
  830. /* adjust the input buffer.  The recovery in question is either  */
  831. /* the insertion of one or more scopes, the merging of the error */
  832. /* token with its successor, the deletion of the error token,    */
  833. /* the insertion of a single token in front of the error token   */
  834. /* or the substitution of another token for the error token.     */
  835. /*****************************************************************/
  836. RepairCandidate DiagnoseParser::PrimaryDiagnosis(PrimaryRepairInfo repair)
  837. {
  838.     RepairCandidate candidate;
  839.  
  840.     int name_index;
  841.  
  842. /*****************************************************************/
  843. /*  Issue diagnostic.                                            */
  844. /*****************************************************************/
  845.     TokenObject prevtok = buffer[repair.buffer_position - 1],
  846.                 curtok  = buffer[repair.buffer_position];
  847.  
  848.     switch(repair.code)
  849.     {
  850.         case INSERTION_CODE: case BEFORE_CODE:
  851.         {
  852.             if (repair.symbol > NT_OFFSET)
  853.                  name_index = GetNtermIndex(stack[state_stack_top],
  854.                                             repair.symbol,
  855.                                             repair.buffer_position);
  856.             else name_index = GetTermIndex(stack,
  857.                                            state_stack_top,
  858.                                            repair.symbol,
  859.                                            repair.buffer_position);
  860. //
  861. //            TokenObject t = curtok;
  862. //            if (repair.code == INSERTION_CODE)
  863. //            {
  864. //                if (repair.symbol != EOLT_SYMBOL && lex_stream -> AfterEol(curtok))
  865. //                     repair.code = BEFORE_CODE;
  866. //                else t = prevtok;
  867. //            }
  868. // 
  869. //            error.report(0, repair.code, name_index, Loc(t), t);
  870. //
  871.             TokenObject t = (repair.code == INSERTION_CODE ? prevtok : curtok);
  872.             error.Report(0, repair.code, name_index, Loc(t), t);
  873.             break;
  874.         }
  875.         case INVALID_CODE:
  876.         {
  877.             name_index = GetNtermIndex(stack[state_stack_top],
  878.                                        repair.symbol,
  879.                                        repair.buffer_position + 1);
  880.             error.Report(0, repair.code, name_index, Loc(curtok), curtok);
  881.             break;
  882.         }
  883.         case SUBSTITUTION_CODE:
  884.         {
  885.             if (repair.misspell_index >= 6)
  886.                 name_index = terminal_index[repair.symbol];
  887.             else
  888.             {
  889.                 name_index = GetTermIndex(stack, state_stack_top,
  890.                                           repair.symbol,
  891.                                           repair.buffer_position + 1);
  892.                 if (name_index != terminal_index[repair.symbol])
  893.                     repair.code = INVALID_CODE;
  894.             }
  895.             error.Report(0, repair.code, name_index, Loc(curtok), curtok);
  896.             break;
  897.         }
  898.         case MERGE_CODE:
  899.         {
  900.             error.Report(0, repair.code, terminal_index[repair.symbol],
  901.                                          Loc(curtok), lex_stream -> Next(curtok));
  902.             break;
  903.         }
  904. #if defined(SCOPE_REPAIR)
  905.         case SCOPE_CODE:
  906.         {
  907.             for (int i = 0; i < scope_stack_top; i++)
  908.             {
  909.                 error.Report(0, repair.code,
  910.                                 -scope_index[i],
  911.                                 location_stack[scope_position[i]],
  912.                                 prevtok,
  913.                                 non_terminal_index[scope_lhs[scope_index[i]]]);
  914.             }
  915.  
  916.             repair.symbol = scope_lhs[scope_index[scope_stack_top]] + NT_OFFSET;
  917.             state_stack_top = scope_position[scope_stack_top];
  918.             error.Report(0, repair.code,
  919.                             -scope_index[scope_stack_top],
  920.                             location_stack[scope_position[scope_stack_top]],
  921.                             prevtok,
  922.                             GetNtermIndex(stack[state_stack_top],
  923.                                           repair.symbol,
  924.                                           repair.buffer_position)
  925.                            );
  926.             break;
  927.         }
  928. #endif
  929.         default: /* deletion */
  930.         {
  931.             error.Report(0, repair.code, terminal_index[ERROR_SYMBOL],
  932.                                          Loc(curtok), curtok);
  933.         }
  934.     }
  935.  
  936. /*****************************************************************/
  937. /*  Update buffer.                                               */
  938. /*****************************************************************/
  939.     switch (repair.code)
  940.     {
  941.         case INSERTION_CODE: case BEFORE_CODE:
  942. #if defined(SCOPE_REPAIR)
  943.         case SCOPE_CODE:
  944. #endif
  945.         {
  946.             candidate.symbol = repair.symbol;
  947.             candidate.location = Loc(buffer[repair.buffer_position]);
  948.             lex_stream -> Reset(buffer[repair.buffer_position]);
  949.  
  950.             break;
  951.         }
  952.  
  953.         case INVALID_CODE: case SUBSTITUTION_CODE:
  954.         {
  955.             candidate.symbol = repair.symbol;
  956.             candidate.location = Loc(buffer[repair.buffer_position]);
  957.             lex_stream -> Reset(buffer[repair.buffer_position + 1]);
  958.  
  959.             break;
  960.         }
  961.  
  962.         case MERGE_CODE:
  963.         {
  964.             candidate.symbol = repair.symbol;
  965.             candidate.location = Loc(buffer[repair.buffer_position]);
  966.             lex_stream -> Reset(buffer[repair.buffer_position + 2]);
  967.  
  968.             break;
  969.         }
  970.  
  971.         default: /* deletion */
  972.         {
  973.             candidate.location = Loc(buffer[repair.buffer_position + 1]);
  974.             candidate.symbol =
  975.                       lex_stream -> Kind(buffer[repair.buffer_position + 1]);
  976.             lex_stream -> Reset(buffer[repair.buffer_position + 2]);
  977.  
  978.             break;
  979.         }
  980.     }
  981.  
  982.     return candidate;
  983. }
  984.  
  985.  
  986. /*****************************************************************/
  987. /* This function takes as parameter an integer STACK_TOP that    */
  988. /* points to a STACK element containing the state on which a     */
  989. /* primary recovery will be made; the terminal candidate on which*/
  990. /* to recover; and an integer: buffer_position, which points to  */
  991. /* the position of the next input token in the BUFFER.  The      */
  992. /* parser is simulated until a shift (or shift-reduce) action    */
  993. /* is computed on the candidate.  Then we proceed to compute the */
  994. /* the name index of the highest level nonterminal that can      */
  995. /* directly or indirectly produce the candidate.                 */
  996. /*****************************************************************/
  997. int DiagnoseParser::GetTermIndex(int stck[], int stack_top,
  998.                                  int tok, int buffer_position)
  999. {
  1000. /*****************************************************************/
  1001. /* Initialize stack index of temp_stack and initialize maximum   */
  1002. /* position of state stack that is still useful.                 */
  1003. /*****************************************************************/
  1004.     int act = stck[stack_top],
  1005.         max_pos = stack_top,
  1006.         highest_symbol = tok;
  1007.  
  1008.     temp_stack_top = stack_top - 1;
  1009.  
  1010. /*****************************************************************/
  1011. /* Compute all reduce and associated actions induced by the      */
  1012. /* candidate until a SHIFT or SHIFT-REDUCE is computed. ERROR    */
  1013. /* and ACCEPT actions cannot be computed on the candidate in     */
  1014. /* this context, since we know that it is suitable for recovery. */
  1015. /*****************************************************************/
  1016.     lex_stream -> Reset(buffer[buffer_position]);
  1017.     act = t_action(act, tok, lex_stream);
  1018.     while(act <= NUM_RULES)
  1019.     {
  1020.         /*********************************************************/
  1021.         /* Process all goto-reduce actions following reduction,  */
  1022.         /* until a goto action is computed ...                   */
  1023.         /*********************************************************/
  1024.         do
  1025.         {
  1026.             temp_stack_top -= (rhs[act]-1);
  1027.             int lhs_symbol = lhs[act];
  1028.             act = (temp_stack_top > max_pos
  1029.                                   ? temp_stack[temp_stack_top]
  1030.                                   : stck[temp_stack_top]);
  1031.             act = nt_action(act, lhs_symbol);
  1032.         } while(act <= NUM_RULES);
  1033.         /*********************************************************/
  1034.         /* Compute new maximum useful position of (STATE_)stack, */
  1035.         /* push goto state into the stack, and compute next      */
  1036.         /* action on candidate ...                               */
  1037.         /*********************************************************/
  1038.         max_pos = Min(max_pos, temp_stack_top);
  1039.         temp_stack[temp_stack_top + 1] = act;
  1040.         act = t_action(act, tok, lex_stream);
  1041.     }
  1042.  
  1043. /********************************************************************/
  1044. /* At this stage, we have simulated all actions induced by the      */
  1045. /* candidate and we are ready to shift or shift-reduce it. First,   */
  1046. /* set tok and next_ptr appropriately and identify the candidate    */
  1047. /* as the initial highest_symbol. If a shift action was computed    */
  1048. /* on the candidate, update the stack and compute the next          */
  1049. /* action. Next, simulate all actions possible on the next input    */
  1050. /* token until we either have to shift it or are about to reduce    */
  1051. /* below the initial starting point in the stack (indicated by      */
  1052. /* max_pos as computed in the previous loop).  At that point,       */
  1053. /* return the highest_symbol computed.                              */
  1054. /********************************************************************/
  1055.     temp_stack_top++;   /* adjust top of stack to reflect last goto */
  1056.                         /* next move is shift or shift-reduce.      */
  1057.     int threshold = temp_stack_top;
  1058.  
  1059.     tok = lex_stream -> Kind(buffer[buffer_position]);
  1060.     lex_stream -> Reset(buffer[buffer_position + 1]);
  1061.  
  1062.     if (act > ERROR_ACTION)   /* shift-reduce on candidate? */
  1063.         act -= ERROR_ACTION;
  1064.     else                      /* shift on candidate ! */
  1065.     {
  1066.         temp_stack[temp_stack_top + 1] = act;
  1067.         act = t_action(act, tok, lex_stream);
  1068.     }
  1069.  
  1070.     while(act <= NUM_RULES)
  1071.     {
  1072.         /*********************************************************/
  1073.         /* Process all goto-reduce actions following reduction,  */
  1074.         /* until a goto action is computed ...                   */
  1075.         /*********************************************************/
  1076.         do
  1077.         {
  1078.             temp_stack_top -= (rhs[act]-1);
  1079.  
  1080.             if (temp_stack_top < threshold)
  1081.                 goto quit;
  1082.  
  1083.             int lhs_symbol = lhs[act];
  1084.             if (temp_stack_top == threshold)
  1085.                 highest_symbol = lhs_symbol + NT_OFFSET;
  1086.             act = (temp_stack_top > max_pos
  1087.                                   ? temp_stack[temp_stack_top]
  1088.                                   : stck[temp_stack_top]);
  1089.             act = nt_action(act, lhs_symbol);
  1090.         } while(act <= NUM_RULES);
  1091.  
  1092.         temp_stack[temp_stack_top + 1] = act;
  1093.         act = t_action(act, tok, lex_stream);
  1094.     }
  1095.  
  1096.  quit:
  1097.     return (highest_symbol > NT_OFFSET
  1098.                            ? non_terminal_index[highest_symbol - NT_OFFSET]
  1099.                            : terminal_index[highest_symbol]);
  1100. }
  1101.  
  1102. /*****************************************************************/
  1103. /* This function takes as parameter a starting state number:     */
  1104. /* start, a nonterminal symbol, A (candidate), and an integer,   */
  1105. /* buffer_position,  which points to the position of the next    */
  1106. /* input token in the BUFFER.                                    */
  1107. /* It returns the highest level non-terminal B such that         */
  1108. /* B =>*rm A.  I.e., there does not exists a nonterminal C such  */
  1109. /* that C =>+rm B. (Recall that for an LALR(k) grammar if        */
  1110. /* C =>+rm B, it cannot be the case that B =>+rm C)              */
  1111. /*****************************************************************/
  1112. int DiagnoseParser::GetNtermIndex(int start, int sym, int buffer_position)
  1113. {
  1114.     int act,
  1115.         tok,
  1116.         highest_symbol;
  1117.  
  1118.     highest_symbol = sym - NT_OFFSET;
  1119.  
  1120.     tok = lex_stream -> Kind(buffer[buffer_position]);
  1121.     lex_stream -> Reset(buffer[buffer_position + 1]);
  1122.  
  1123. /*****************************************************************/
  1124. /* Initialize stack index of temp_stack and initialize maximum   */
  1125. /* position of state stack that is still useful.                 */
  1126. /*****************************************************************/
  1127.     temp_stack_top = 0;
  1128.     temp_stack[temp_stack_top] = start;
  1129.  
  1130.     act = nt_action(start, highest_symbol);
  1131.     if (act > NUM_RULES) /* goto action? */
  1132.     {
  1133.         temp_stack[temp_stack_top + 1] = act;
  1134.         act = t_action(act, tok, lex_stream);
  1135.     }
  1136.  
  1137.     while(act <= NUM_RULES)
  1138.     {
  1139.         /*********************************************************/
  1140.         /* Process all goto-reduce actions following reduction,  */
  1141.         /* until a goto action is computed ...                   */
  1142.         /*********************************************************/
  1143.         do
  1144.         {
  1145.             temp_stack_top -= (rhs[act]-1);
  1146.             if (temp_stack_top < 0)
  1147.                 return non_terminal_index[highest_symbol];
  1148.             if (temp_stack_top == 0)
  1149.                 highest_symbol = lhs[act];
  1150.             act = nt_action(temp_stack[temp_stack_top], lhs[act]);
  1151.         } while(act <= NUM_RULES);
  1152.         temp_stack[temp_stack_top + 1] = act;
  1153.         act = t_action(act, tok, lex_stream);
  1154.     }
  1155.  
  1156.     return non_terminal_index[highest_symbol];
  1157. }
  1158.  
  1159.  
  1160. /*****************************************************************/
  1161. /*     Check whether or not there is a high probability that a   */
  1162. /* given string is a misspelling of another.                     */
  1163. /* Certain singleton symbols (such as ":" and ";") are also      */
  1164. /* considered to be misspelling of each other.                   */
  1165. /*****************************************************************/
  1166. int DiagnoseParser::Misspell(int sym, TokenObject tok)
  1167. {
  1168.     int len = name_length[terminal_index[sym]];
  1169.         
  1170.     wchar_t *keyword = new wchar_t[len + 1];
  1171.     for (int i = name_start[terminal_index[sym]], j = 0; j < len; i++, j++)
  1172.     {
  1173.         wchar_t c = string_buffer[i];
  1174. #ifdef EBCDIC
  1175.         c = Code::ToASCII(c);
  1176. #endif
  1177.         keyword[j] = c;
  1178.     }
  1179.     keyword[len] = U_NULL;
  1180.  
  1181.     int index = Spell::Index(lex_stream -> Name(tok), keyword);
  1182.  
  1183.     delete [] keyword;
  1184.  
  1185.     return index;
  1186. }
  1187.  
  1188.  
  1189. /*****************************************************************/
  1190. /*****************************************************************/
  1191. PrimaryRepairInfo DiagnoseParser::ScopeTrial(int stck[], int stack_top,
  1192.                                              PrimaryRepairInfo repair)
  1193. {
  1194.     state_seen = new int[stack_length];
  1195.     for (int i = 0; i < stack_length; i++)
  1196.         state_seen[i] = NIL;
  1197.  
  1198.     ScopeTrialCheck(stck, stack_top, repair, 0);
  1199.  
  1200.     delete [] state_seen;
  1201.     state_pool.Reset();
  1202.  
  1203.     repair.code = SCOPE_CODE;
  1204.     repair.misspell_index = 10;
  1205.  
  1206.     return repair;
  1207. }
  1208.  
  1209.  
  1210. /*****************************************************************/
  1211. /* SCOPE_TRIAL_CHECK is a recursive procedure that takes as arguments  */
  1212. /* a state configuration: STACK and STACK_TOP, and an integer:   */
  1213. /* INDX. In addition, a global variable SCOPE_DISTANCE indicates */
  1214. /* the distance to "beat" and SCOPE_BUFFER_POSITION identifies   */
  1215. /* the starting position of the next input tokens in BUFFER.     */
  1216. /* SCOPE_TRIAL determines whether or not scope recovery is       */
  1217. /* possible.  If so, it uses two global arrays: SCOPE_INDEX and  */
  1218. /* SCOPE_LOCATION to store the necessary information about the   */
  1219. /* scopes to be closed. A global variable, scope_stack_top, identifies */
  1220. /* the highest element used in these arrays.                     */
  1221. /* The global variable SCOPE_DISTANCE is also updated to reflect */
  1222. /* the new result.                                               */
  1223. /*****************************************************************/
  1224. void DiagnoseParser::ScopeTrialCheck(int stck[], int stack_top,
  1225.                                      PrimaryRepairInfo& repair, int indx)
  1226. {
  1227.     int max_pos,
  1228.         marked_pos,
  1229.         stack_position,
  1230.         distance,
  1231.         previous_distance,
  1232.         i,
  1233.         j,
  1234.         k,
  1235.         act,
  1236.         tok,
  1237.         lhs_symbol;
  1238.  
  1239.     act = stck[stack_top];
  1240.  
  1241.     for (i = state_seen[stack_top]; i != NIL; i = state_pool[i].next)
  1242.         if (state_pool[i].state == act)
  1243.             return;
  1244.  
  1245.     i = state_pool.NextIndex();
  1246.     state_pool[i].state = act;
  1247.     state_pool[i].next  = state_seen[stack_top];
  1248.     state_seen[stack_top] = i;
  1249.  
  1250.     for (i = 0; i < SCOPE_SIZE; i++)
  1251.     {
  1252.         /*********************************************************/
  1253.         /* Use the scope lookahead symbol to force all reductions*/
  1254.         /* inducible by that symbol.                             */
  1255.         /*********************************************************/
  1256.         act = stck[stack_top];
  1257.         temp_stack_top = stack_top - 1;
  1258.         max_pos = stack_top;
  1259.         tok = scope_la[i];
  1260.         lex_stream -> Reset(buffer[repair.buffer_position]);
  1261.         act = t_action(act, tok, lex_stream);
  1262.         while(act <= NUM_RULES)
  1263.         {
  1264.             /*************************************************/
  1265.             /* ... Process all goto-reduce actions following */
  1266.             /* reduction, until a goto action is computed ...*/
  1267.             /*************************************************/
  1268.             do
  1269.             {
  1270.                 temp_stack_top -= (rhs[act]-1);
  1271.                 lhs_symbol = lhs[act];
  1272.                 act =  (temp_stack_top > max_pos
  1273.                             ?  temp_stack[temp_stack_top]
  1274.                             :  stck[temp_stack_top]);
  1275.                 act = nt_action(act, lhs_symbol);
  1276.             }  while(act <= NUM_RULES);
  1277.             if (temp_stack_top + 1 >= stack_length)
  1278.                 return;
  1279.             max_pos = Min(max_pos, temp_stack_top);
  1280.             temp_stack[temp_stack_top + 1] = act;
  1281.             act = t_action(act, tok, lex_stream);
  1282.         }
  1283.  
  1284.         /*********************************************************/
  1285.         /* If the lookahead symbol is parsable, then we check    */
  1286.         /* whether or not we have a match between the scope      */
  1287.         /* prefix and the transition symbols corresponding to    */
  1288.         /* the states on top of the stack.                       */
  1289.         /*********************************************************/
  1290.         if (act != ERROR_ACTION)
  1291.         {
  1292.             k = scope_prefix[i];
  1293.             for (j = temp_stack_top + 1;
  1294.                  j >= (max_pos + 1) &&
  1295.                  in_symbol(temp_stack[j]) == scope_rhs[k]; j--)
  1296.                  k++;
  1297.             if (j == max_pos)
  1298.                 for (j = max_pos;
  1299.                      j >= 1 && in_symbol(stck[j]) == scope_rhs[k];
  1300.                      j--)
  1301.                     k++;
  1302.             /*****************************************************/
  1303.             /* If the prefix matches, check whether the state    */
  1304.             /* newly exposed on top of the stack, (after the     */
  1305.             /* corresponding prefix states are popped from the   */
  1306.             /* stack), is in the set of "source states" for the  */
  1307.             /* scope in question and that it is at a position    */
  1308.             /* below the threshold indicated by MARKED_POS.      */
  1309.             /*****************************************************/
  1310.             marked_pos = (max_pos < stack_top ? max_pos + 1
  1311.                                               : stack_top);
  1312.             if (scope_rhs[k] == 0 && j < marked_pos)   /* match? */
  1313.             {
  1314.                 stack_position = j;
  1315.                 for (j = scope_state_set[i];
  1316.                      stck[stack_position] != scope_state[j] &&
  1317.                      scope_state[j] != 0;
  1318.                      j++);
  1319.                 /*************************************************/
  1320.                 /* If the top state is valid for scope recovery, */
  1321.                 /* the left-hand side of the scope is used as    */
  1322.                 /* starting symbol and we calculate how far the  */
  1323.                 /* parser can advance within the forward context */
  1324.                 /* after parsing the left-hand symbol.           */
  1325.                 /*************************************************/
  1326.                 if (scope_state[j] != 0)      /* state was found */
  1327.                 {
  1328.                     previous_distance = repair.distance;
  1329.                     distance = ParseCheck(stck,
  1330.                                           stack_position,
  1331.                                           scope_lhs[i]+NT_OFFSET,
  1332.                                           repair.buffer_position);
  1333.                     /*********************************************/
  1334.                     /* if the recovery is not successful, we     */
  1335.                     /* update the stack with all actions induced */
  1336.                     /* by the left-hand symbol, and recursively  */
  1337.                     /* call SCOPE_TRIAL_CHECK to try again.      */
  1338.                     /* Otherwise, the recovery is successful. If */
  1339.                     /* the new distance is greater than the      */
  1340.                     /* initial SCOPE_DISTANCE, we update         */
  1341.                     /* SCOPE_DISTANCE and set scope_stack_top to INDX  */
  1342.                     /* to indicate the number of scopes that are */
  1343.                     /* to be applied for a succesful  recovery.  */
  1344.                     /* NOTE that this procedure cannot get into  */
  1345.                     /* an infinite loop, since each prefix match */
  1346.                     /* is guaranteed to take us to a lower point */
  1347.                     /* within the stack.                         */
  1348.                     /*********************************************/
  1349.                     if ((distance - repair.buffer_position + 1) <
  1350.                         MIN_DISTANCE)
  1351.                     {
  1352.                         int top = stack_position;
  1353.                         act = nt_action(stck[top], scope_lhs[i]);
  1354.                         while(act <= NUM_RULES)
  1355.                         {
  1356.                             top -= (rhs[act]-1);
  1357.                             act = nt_action(stck[top], lhs[act]);
  1358.                         }
  1359.                         top++;
  1360.  
  1361.                         j = act;
  1362.                         act = stck[top];  /* save */
  1363.                         stck[top] = j;    /* swap */
  1364.                         ScopeTrialCheck(stck, top, repair, indx+1);
  1365.                         stck[top] = act; /* restore */
  1366.                     }
  1367.                     else if (distance > repair.distance)
  1368.                     {
  1369.                         scope_stack_top = indx;
  1370.                         repair.distance = distance;
  1371.                     }
  1372.  
  1373.                     if (lex_stream -> Kind(buffer[repair.buffer_position]) ==
  1374.                         EOFT_SYMBOL &&
  1375.                         repair.distance == previous_distance)
  1376.                     {
  1377.                         scope_stack_top = indx;
  1378.                         repair.distance = MAX_DISTANCE;
  1379.                     }
  1380.  
  1381.                     /*********************************************/
  1382.                     /* If this scope recovery has beaten the     */
  1383.                     /* previous distance, then we have found a   */
  1384.                     /* better recovery (or this recovery is one  */
  1385.                     /* of a list of scope recoveries). Record    */
  1386.                     /* its information at the proper location    */
  1387.                     /* (INDX) in SCOPE_INDEX and SCOPE_STACK.    */
  1388.                     /*********************************************/
  1389.                     if (repair.distance > previous_distance)
  1390.                     {
  1391.                         scope_index[indx] = i;
  1392.                         scope_position[indx] = stack_position;
  1393.                         return;
  1394.                     }
  1395.                 }
  1396.             }
  1397.         }
  1398.     }
  1399.  
  1400.     return;
  1401. }
  1402.  
  1403. /*****************************************************************/
  1404. /* This function computes the ParseCheck distance for the best   */
  1405. /* possible secondary recovery for a given configuration that    */
  1406. /* either deletes none or only one symbol in the forward context.*/
  1407. /* If the recovery found is more effective than the best primary */
  1408. /* recovery previously computed, then the function returns true. */
  1409. /* Only misplacement, scope and manual recoveries are attempted; */
  1410. /* simple insertion or substitution of a nonterminal are tried   */
  1411. /* in CHECK_PRIMARY_DISTANCE as part of primary recovery.        */
  1412. /*****************************************************************/
  1413. bool DiagnoseParser::SecondaryCheck(int stck[], int stack_top,
  1414.                                     int buffer_position, int distance)
  1415. {
  1416.     PrimaryRepairInfo repair;
  1417.     
  1418.     int top,
  1419.         j;
  1420.  
  1421.     for (top = stack_top - 1; top >= 0; top--)
  1422.     {
  1423.         j = ParseCheck(stck, top,
  1424.                        lex_stream -> Kind(buffer[buffer_position]),
  1425.                        buffer_position + 1);
  1426.         if (((j - buffer_position + 1) > MIN_DISTANCE) &&
  1427.             (j > distance))
  1428.             return true;
  1429.     }
  1430.  
  1431. #if defined(SCOPE_REPAIR)
  1432.     repair.buffer_position = buffer_position + 1;
  1433.     repair.distance = distance;
  1434.     repair = ScopeTrial(stck, stack_top, repair);
  1435.     if ((repair.distance - buffer_position) > MIN_DISTANCE &&
  1436.         repair.distance > distance)
  1437.          return true;
  1438. //#elif !defined(SCOPE_REPAIR)
  1439. //    manual_buffer_position = buffer_position + 1;
  1440. //    manual_distance = distance;
  1441. //    manual_trial(stck, stack_top);
  1442. //    if ((manual_distance - repair.buffer_position) > MIN_DISTANCE &&
  1443. //        manual_distance > distance)
  1444. //         return true;
  1445. #endif
  1446.  
  1447.     return false;
  1448. }
  1449.  
  1450.  
  1451. /*****************************************************************/
  1452. /* Secondary_phase is a boolean function that checks whether or  */
  1453. /* not some form of secondary recovery is applicable to one of   */
  1454. /* the error configurations. First, if "next_stack" is available,*/
  1455. /* misplacement and secondary recoveries are attempted on it.    */
  1456. /* Then, in any case, these recoveries are attempted on "stack". */
  1457. /* If a successful recovery is found, a diagnosis is issued, the */
  1458. /* configuration is updated and the function returns "true".     */
  1459. /* Otherwise, the function returns false.                        */
  1460. /*****************************************************************/
  1461. RepairCandidate DiagnoseParser::SecondaryPhase(TokenObject error_token)
  1462. {
  1463.     SecondaryRepairInfo repair,
  1464.                           misplaced;
  1465.  
  1466.     RepairCandidate candidate;
  1467.  
  1468.     int i,
  1469.         j,
  1470.         k,
  1471.         top,
  1472.         next_last_index,
  1473.         last_index;
  1474.  
  1475.     candidate.symbol = 0;
  1476.  
  1477.     repair.code = 0;
  1478.     repair.distance = 0;
  1479.     repair.recovery_on_next_stack = false;
  1480.  
  1481.     misplaced.distance = 0;
  1482.     misplaced.recovery_on_next_stack = false;
  1483.  
  1484. /*****************************************************************/
  1485. /* If the next_stack is available, try misplaced and secondary   */
  1486. /* recovery on it first.                                         */
  1487. /*****************************************************************/
  1488.     if (next_stack_top >= 0)
  1489.     {
  1490.         Location  save_location;
  1491.  
  1492.         buffer[2] = error_token;
  1493.         buffer[1] = lex_stream -> Previous(buffer[2]);
  1494.         buffer[0] = lex_stream -> Previous(buffer[1]);
  1495.  
  1496.         for (k = 3; k < BUFF_UBOUND; k++)
  1497.             buffer[k] = lex_stream -> Next(buffer[k - 1]);
  1498.  
  1499.         buffer[BUFF_UBOUND] = lex_stream -> Badtoken();/* elmt not available */
  1500.  
  1501.         /*********************************************************/
  1502.         /* If we are at the end of the input stream, compute the */
  1503.         /* index position of the first EOFT symbol (last useful  */
  1504.         /* index).                                               */
  1505.         /*********************************************************/
  1506.         for (next_last_index = MAX_DISTANCE - 1;
  1507.              next_last_index >= 1 &&
  1508.              lex_stream -> Kind(buffer[next_last_index]) == EOFT_SYMBOL;
  1509.              next_last_index--);
  1510.         next_last_index = next_last_index + 1;
  1511.  
  1512.         save_location = location_stack[next_stack_top];
  1513.         location_stack[next_stack_top] = Loc(buffer[2]);
  1514.         misplaced.num_deletions = next_stack_top;
  1515.         misplaced = MisplacementRecovery(next_stack, next_stack_top,
  1516.                                          next_last_index,
  1517.                                          misplaced, true);
  1518.         if (misplaced.recovery_on_next_stack)
  1519.             misplaced.distance++;
  1520.  
  1521.         repair.num_deletions = next_stack_top + BUFF_UBOUND;
  1522.         repair = SecondaryRecovery(next_stack, next_stack_top,
  1523.                                    next_last_index,
  1524.                                    repair, true);
  1525.         if (repair.recovery_on_next_stack)
  1526.             repair.distance++;
  1527.  
  1528.         location_stack[next_stack_top] = save_location;
  1529.     }
  1530.     else             /* next_stack not available, initialize ... */
  1531.     {
  1532.         misplaced.num_deletions = state_stack_top;
  1533.         repair.num_deletions = state_stack_top + BUFF_UBOUND;
  1534.     }
  1535.  
  1536. /*****************************************************************/
  1537. /* Try secondary recovery on the "stack" configuration.          */
  1538. /*****************************************************************/
  1539.     buffer[3] = error_token;
  1540.  
  1541.     buffer[2] = lex_stream -> Previous(buffer[3]);
  1542.     buffer[1] = lex_stream -> Previous(buffer[2]);
  1543.     buffer[0] = lex_stream -> Previous(buffer[1]);
  1544.  
  1545.     for (k = 4; k < BUFF_SIZE; k++)
  1546.         buffer[k] = lex_stream -> Next(buffer[k - 1]);
  1547.  
  1548.     for (last_index = MAX_DISTANCE - 1;
  1549.          last_index >= 1 && lex_stream -> Kind(buffer[last_index]) == EOFT_SYMBOL;
  1550.          last_index--);
  1551.     last_index++;
  1552.  
  1553.     misplaced = MisplacementRecovery(stack, state_stack_top,
  1554.                                      last_index,
  1555.                                      misplaced, false);
  1556.  
  1557.     repair = SecondaryRecovery(stack, state_stack_top,
  1558.                                last_index, repair, false);
  1559.  
  1560. /*****************************************************************/
  1561. /* If a successful misplaced recovery was found, compare it with */
  1562. /* the most successful secondary recovery.  If the misplaced     */
  1563. /* recovery either deletes fewer symbols or parse-checks further */
  1564. /* then it is chosen.                                            */
  1565. /*****************************************************************/
  1566.     if (misplaced.distance > MIN_DISTANCE)
  1567.     {
  1568.         if (misplaced.num_deletions <= repair.num_deletions ||
  1569.            (misplaced.distance - misplaced.num_deletions) >=
  1570.            (repair.distance - repair.num_deletions))
  1571.         {
  1572.             repair.code = MISPLACED_CODE;
  1573.             repair.stack_position = misplaced.stack_position;
  1574.             repair.buffer_position = 2;
  1575.             repair.num_deletions = misplaced.num_deletions;
  1576.             repair.distance = misplaced.distance;
  1577.             repair.recovery_on_next_stack = misplaced.recovery_on_next_stack;
  1578.         }
  1579.     }
  1580.  
  1581. /*****************************************************************/
  1582. /* If the successful recovery was on next_stack, update: stack,  */
  1583. /* buffer, location_stack and last_index.                        */
  1584. /*****************************************************************/
  1585.     if (repair.recovery_on_next_stack)
  1586.     {
  1587.         state_stack_top = next_stack_top;
  1588.         for (i = 0; i <= state_stack_top; i++)
  1589.             stack[i] = next_stack[i];
  1590.  
  1591.         buffer[2] = error_token;
  1592.         buffer[1] = lex_stream -> Previous(buffer[2]);
  1593.         buffer[0] = lex_stream -> Previous(buffer[1]);
  1594.  
  1595.         for (k = 3; k < BUFF_UBOUND; k++)
  1596.             buffer[k] = lex_stream -> Next(buffer[k - 1]);
  1597.  
  1598.         buffer[BUFF_UBOUND] = lex_stream -> Badtoken();/* elmt not available */
  1599.  
  1600.         location_stack[next_stack_top] = Loc(buffer[2]);
  1601.         last_index = next_last_index;
  1602.     }
  1603.  
  1604. #if defined(SCOPE_REPAIR)
  1605. /*****************************************************************/
  1606. /* Next, try scope recoveries after deletion of one, two, three, */
  1607. /* four ... buffer_position tokens from the input stream.        */
  1608. /*****************************************************************/
  1609.     if (repair.code == SECONDARY_CODE ||
  1610.         repair.code == DELETION_CODE)
  1611.     {
  1612.         PrimaryRepairInfo scope_repair;
  1613.         
  1614.         scope_repair.distance = 0;
  1615.         for (scope_repair.buffer_position = 2;
  1616.              scope_repair.buffer_position <= repair.buffer_position &&
  1617.              repair.code != SCOPE_CODE; scope_repair.buffer_position++)
  1618.         {
  1619.             scope_repair = ScopeTrial(stack, state_stack_top, scope_repair);
  1620.             j = (scope_repair.distance == MAX_DISTANCE
  1621.                                         ? last_index
  1622.                                         : scope_repair.distance);
  1623.             k = scope_repair.buffer_position - 1;
  1624.             if ((j - k) > MIN_DISTANCE &&
  1625.                 (j - k) > (repair.distance - repair.num_deletions))
  1626.             {
  1627.                 repair.code = SCOPE_CODE;
  1628.                 i = scope_index[scope_stack_top];       /* upper bound */
  1629.                 repair.symbol = scope_lhs[i] + NT_OFFSET;
  1630.                 repair.stack_position = state_stack_top;
  1631.                 repair.buffer_position = scope_repair.buffer_position;
  1632.             }
  1633.         }
  1634.     }
  1635.  
  1636. /*****************************************************************/
  1637. /* If no successful recovery is found and we have reached the    */
  1638. /* end of the file, check whether or not scope recovery is       */
  1639. /* applicable at the end of the file after discarding some       */
  1640. /* states.                                                       */
  1641. /*****************************************************************/
  1642.     if (repair.code == 0 &&
  1643.         lex_stream -> Kind(buffer[last_index]) == EOFT_SYMBOL)
  1644.     {
  1645.         PrimaryRepairInfo scope_repair;
  1646.  
  1647.         scope_repair.buffer_position = last_index;
  1648.         scope_repair.distance = 0;
  1649.         for (top = state_stack_top;
  1650.              top >= 0 && repair.code == 0; top--)
  1651.         {
  1652.             scope_repair = ScopeTrial(stack, top, scope_repair);
  1653.             if (scope_repair.distance > 0)
  1654.             {
  1655.                 repair.code = SCOPE_CODE;
  1656.                 i = scope_index[scope_stack_top];    /* upper bound */
  1657.                 repair.symbol = scope_lhs[i] + NT_OFFSET;
  1658.                 repair.stack_position = top;
  1659.                 repair.buffer_position = scope_repair.buffer_position;
  1660.             }
  1661.         }
  1662.     }
  1663.  
  1664. #endif
  1665.  
  1666. /*****************************************************************/
  1667. /* If a successful repair was not found, quit!  Otherwise, issue */
  1668. /* diagnosis and adjust configuration...                         */
  1669. /*****************************************************************/
  1670.     if (repair.code == 0)
  1671.         return candidate;
  1672.  
  1673.     SecondaryDiagnosis(repair);
  1674.  
  1675. /*****************************************************************/
  1676. /* Update buffer based on number of elements that are deleted.   */
  1677. /*****************************************************************/
  1678.     switch(repair.code)
  1679.     {
  1680.         case MANUAL_CODE: case MISPLACED_CODE:
  1681.              candidate.location = Loc(buffer[2]);
  1682.              candidate.symbol = lex_stream -> Kind(buffer[2]);
  1683.              lex_stream -> Reset(lex_stream -> Next(buffer[2]));
  1684.  
  1685.              break;
  1686.  
  1687.         case DELETION_CODE:
  1688.              candidate.location = Loc(buffer[repair.buffer_position]);
  1689.              candidate.symbol =
  1690.                        lex_stream -> Kind(buffer[repair.buffer_position]);
  1691.              lex_stream -> Reset(lex_stream -> Next(buffer[repair.buffer_position]));
  1692.  
  1693.              break;
  1694.  
  1695.         default: /* SCOPE_CODE || SECONDARY_CODE */
  1696.              candidate.symbol = repair.symbol;
  1697.              candidate.location = Loc(buffer[repair.buffer_position]);
  1698.              lex_stream -> Reset(buffer[repair.buffer_position]);
  1699.  
  1700.              break;
  1701.     }
  1702.  
  1703.     return candidate;
  1704. }
  1705.  
  1706.  
  1707. /*****************************************************************/
  1708. /* This boolean function checks whether or not a given           */
  1709. /* configuration yields a better misplacement recovery than      */
  1710. /* the best misplacement recovery computed previously.           */
  1711. /*****************************************************************/
  1712. SecondaryRepairInfo DiagnoseParser::MisplacementRecovery
  1713.          (int stck[], int stack_top, int last_index,
  1714.           SecondaryRepairInfo repair, bool stack_flag)
  1715. {
  1716.     Location  previous_loc = Loc(buffer[2]);
  1717.     int stack_deletions = 0;
  1718.  
  1719.     for (int top = stack_top - 1; top >= 0; top--)
  1720.     {
  1721.         if (location_stack[top] < previous_loc)
  1722.             stack_deletions++;
  1723.         previous_loc = location_stack[top];
  1724.  
  1725.         int j = ParseCheck(stck, top, lex_stream -> Kind(buffer[2]), 3);
  1726.         if (j == MAX_DISTANCE)
  1727.              j = last_index;
  1728.         if ((j > MIN_DISTANCE) &&
  1729.             (j - stack_deletions) >
  1730.             (repair.distance - repair.num_deletions))
  1731.         {
  1732.             repair.stack_position = top;
  1733.             repair.distance = j;
  1734.             repair.num_deletions = stack_deletions;
  1735.             repair.recovery_on_next_stack = stack_flag;
  1736.         }
  1737.     }
  1738.  
  1739.     return repair;
  1740. }
  1741.  
  1742.  
  1743. /*****************************************************************/
  1744. /* This boolean function checks whether or not a given           */
  1745. /* configuration yields a better secondary recovery than the     */
  1746. /* best misplacement recovery computed previously.               */
  1747. /*****************************************************************/
  1748. SecondaryRepairInfo DiagnoseParser::SecondaryRecovery
  1749.          (int stck[],int stack_top,
  1750.           int last_index, SecondaryRepairInfo repair, bool stack_flag)
  1751. {
  1752.     int i,
  1753.         j,
  1754.         k,
  1755.         l,
  1756.         symbol,
  1757.         stack_deletions,
  1758.         top;
  1759.  
  1760.     Location  previous_loc;
  1761.  
  1762.     stack_deletions = 0;
  1763.     previous_loc = Loc(buffer[2]);
  1764.     for (top = stack_top;
  1765.          top >= 0 && repair.num_deletions >= stack_deletions; top--)
  1766.     {
  1767.         if (location_stack[top] < previous_loc)
  1768.             stack_deletions++;
  1769.         previous_loc = location_stack[top];
  1770.  
  1771.         for (i = 2;
  1772.              i <= (last_index - MIN_DISTANCE + 1) &&
  1773.              (repair.num_deletions >= (stack_deletions + i - 1)); i++)
  1774.         {
  1775.             j = ParseCheck(stck, top, lex_stream -> Kind(buffer[i]), i + 1);
  1776.  
  1777.             if (j == MAX_DISTANCE)
  1778.                  j = last_index;
  1779.             if ((j - i + 1) > MIN_DISTANCE)
  1780.             {
  1781.                 k = stack_deletions + i - 1;
  1782.                 if ((k < repair.num_deletions) ||
  1783.                     (j - k) > (repair.distance - repair.num_deletions) ||
  1784.                     ((repair.code == SECONDARY_CODE) &&
  1785.                      (j - k) == (repair.distance -
  1786.                                  repair.num_deletions)))
  1787.                 {
  1788.                     repair.code = DELETION_CODE;
  1789.                     repair.distance = j;
  1790.                     repair.stack_position = top;
  1791.                     repair.buffer_position = i;
  1792.                     repair.num_deletions = k;
  1793.                     repair.recovery_on_next_stack = stack_flag;
  1794.                 }
  1795.             }
  1796.  
  1797.             for (l = nasi(stck[top]); l >= 0 && nasr[l] != 0; l++)
  1798.             {
  1799.                 symbol = nasr[l] + NT_OFFSET;
  1800.                 j = ParseCheck(stck, top, symbol, i);
  1801.                 if (j == MAX_DISTANCE)
  1802.                      j = last_index;
  1803.                 if ((j - i + 1) > MIN_DISTANCE)
  1804.                 {
  1805.                     k = stack_deletions + i - 1;
  1806.                     if (k < repair.num_deletions ||
  1807.                        (j - k) > (repair.distance -
  1808.                                   repair.num_deletions))
  1809.                     {
  1810.                         repair.code = SECONDARY_CODE;
  1811.                         repair.symbol = symbol;
  1812.                         repair.distance = j;
  1813.                         repair.stack_position = top;
  1814.                         repair.buffer_position = i;
  1815.                         repair.num_deletions = k;
  1816.                         repair.recovery_on_next_stack = stack_flag;
  1817.                     }
  1818.                 }
  1819.             }
  1820.         }
  1821.     }
  1822.  
  1823.     return repair;
  1824. }
  1825.  
  1826.  
  1827. /*****************************************************************/
  1828. /* This procedure is invoked to issue a secondary diagnosis and  */
  1829. /* adjust the input buffer.  The recovery in question is either  */
  1830. /* an automatic scope recovery, a manual scope recovery, a       */
  1831. /* secondary substitution or a secondary deletion.               */
  1832. /*****************************************************************/
  1833. void DiagnoseParser::SecondaryDiagnosis(SecondaryRepairInfo repair)
  1834. {
  1835. /*****************************************************************/
  1836. /*  Issue diagnostic.                                            */
  1837. /*****************************************************************/
  1838.     switch(repair.code)
  1839. #if defined(SCOPE_REPAIR)
  1840.     {
  1841.         case SCOPE_CODE:
  1842.         {
  1843.             if (repair.stack_position < state_stack_top)
  1844.             {
  1845.                 error.Report(0, DELETION_CODE,
  1846.                                 terminal_index[ERROR_SYMBOL],
  1847.                                 location_stack[repair.stack_position],
  1848.                                 buffer[1]);
  1849. //                set_location(buffer[1],
  1850. //                             location_stack[repair.stack_position]);
  1851.             }
  1852.             for (int i = 0; i < scope_stack_top; i++)
  1853.             {
  1854.                 error.Report(0, SCOPE_CODE,
  1855.                                 -scope_index[i],
  1856.                                 location_stack[scope_position[i]],
  1857.                                 buffer[1],
  1858.                                 non_terminal_index[scope_lhs[scope_index[i]]]);
  1859.             }
  1860.  
  1861.             repair.symbol = scope_lhs[scope_index[scope_stack_top]] + NT_OFFSET;
  1862.             state_stack_top = scope_position[scope_stack_top];
  1863.             error.Report(0, SCOPE_CODE,
  1864.                             -scope_index[scope_stack_top],
  1865.                             location_stack[scope_position[scope_stack_top]],
  1866.                             buffer[1],
  1867.                             GetNtermIndex(stack[state_stack_top],
  1868.                                           repair.symbol,
  1869.                                           repair.buffer_position)
  1870.                            );
  1871.             break;
  1872.         }
  1873. #endif
  1874.         default:
  1875.         {
  1876.             error.Report(0, repair.code,
  1877.                             (repair.code == SECONDARY_CODE
  1878.                                           ? GetNtermIndex(stack[repair.stack_position],
  1879.                                                           repair.symbol,
  1880.                                                           repair.buffer_position)
  1881.                                           : terminal_index[ERROR_SYMBOL]),
  1882.                             location_stack[repair.stack_position],
  1883.                             buffer[repair.buffer_position - 1]);
  1884.             state_stack_top = repair.stack_position;
  1885.         }
  1886.     }
  1887.  
  1888.     return;
  1889. }
  1890.  
  1891.  
  1892. //
  1893. // This procedure uses a  quick sort algorithm to sort the ERRORS
  1894. // by the left_line_no and left_column_no fields.
  1895. //
  1896. void ParseError::SortMessages()
  1897. {
  1898.      int lower,
  1899.          upper,
  1900.          lostack[32],
  1901.          histack[32];
  1902.  
  1903.      int top,
  1904.          i,
  1905.          j;
  1906.      ErrorInfo pivot, temp;
  1907.  
  1908.      top = 0;
  1909.      lostack[top] = 0;
  1910.      histack[top] = errors.Length() - 1;
  1911.  
  1912.      while(top >= 0)
  1913.      {
  1914.          lower = lostack[top];
  1915.          upper = histack[top];
  1916.          top--;
  1917.  
  1918.          while(upper > lower)
  1919.          {
  1920.              /*********************************************************/
  1921.              /* The array is most-likely almost sorted. Therefore,    */
  1922.              /* we use the middle element as the pivot element.       */
  1923.              /*********************************************************/
  1924.              i = (lower + upper) / 2;
  1925.              pivot = errors[i];
  1926.              errors[i] = errors[lower];
  1927.  
  1928.              /*********************************************************/
  1929.              /* Split the array section indicated by LOWER and UPPER  */
  1930.              /* using ARRAY(LOWER) as the pivot.                      */
  1931.              /*********************************************************/
  1932.              i = lower;
  1933.              for (j = lower + 1; j <= upper; j++)
  1934.                  if ((errors[j].left_token < pivot.left_token) ||
  1935.                  /*****************************************************/
  1936.                  /* When two error messages start in the same location*/
  1937.                  /* and one is nested inside the other, the outer one */
  1938.                  /* is placed first so that it can be printed last.   */
  1939.                  /* Recall that its right-span location is reached    */
  1940.                  /* after the inner one has been completely processed.*/
  1941.                  /*****************************************************/
  1942.                      (errors[j].left_token == pivot.left_token &&
  1943.                       errors[j].right_token > pivot.right_token) ||
  1944.                  /*****************************************************/
  1945.                  /* When two error messages are at the same location  */
  1946.                  /* span, check the NUM field to keep the sort stable.*/
  1947.                  /* When the location spans only a single symbol,     */
  1948.                  /* the one with the lowest "num" is placed first.    */
  1949.                  /*****************************************************/
  1950.                      (errors[j].left_token  == pivot.left_token  &&
  1951.                       errors[j].right_token == pivot.right_token &&
  1952.                       pivot.left_token == pivot.right_token     &&
  1953.                       errors[j].num < pivot.num)                       ||
  1954.                  /*****************************************************/
  1955.                  /* When two error messages are at the same location  */
  1956.                  /* which spans more than one symbol in the source,   */
  1957.                  /* the first message is treated as been nested into  */
  1958.                  /* the second message and (just like the nested case */
  1959.                  /* above) it is placed last in the sorted sequence.  */
  1960.                  /*****************************************************/
  1961.                      (errors[j].left_token  == pivot.left_token  &&
  1962.                       errors[j].right_token == pivot.right_token &&
  1963.                       pivot.left_token < pivot.right_token      &&
  1964.                       errors[j].num > pivot.num))
  1965.                  {
  1966.                      temp = errors[++i];
  1967.                      errors[i] = errors[j];
  1968.                      errors[j] = temp;
  1969.                  }
  1970.              errors[lower] = errors[i];
  1971.              errors[i] = pivot;
  1972.  
  1973.              top++;
  1974.              if ((i - lower) < (upper - i))
  1975.              {
  1976.                  lostack[top] = i + 1;
  1977.                  histack[top] = upper;
  1978.                  upper = i - 1;
  1979.              }
  1980.              else
  1981.              {
  1982.                  histack[top] = i - 1;
  1983.                  lostack[top] = lower;
  1984.                  lower = i + 1;
  1985.              }
  1986.          }
  1987.      }
  1988.  
  1989.      return;
  1990. }
  1991.  
  1992.  
  1993. /*****************************************************************/
  1994. /* This procedure is invoked by an JIKES PARSER or a semantic    */
  1995. /* routine to process an error message.  The JIKES parser always */
  1996. /* passes the value 0 to msg_level to indicate an error.         */
  1997. /* This routine simply stores all necessary information about    */
  1998. /* the message into an array: error.                             */
  1999. /*****************************************************************/
  2000. void ParseError::Report(int msg_level,
  2001.                         int msg_code,
  2002.                         int name_index,
  2003.                         LexStream::TokenIndex left_token,
  2004.                         LexStream::TokenIndex right_token,
  2005.                         int scope_name_index)
  2006. {
  2007.     int i = errors.NextIndex();
  2008.  
  2009.     errors[i].msg_level           = msg_level;
  2010.     errors[i].msg_code            = msg_code;
  2011.     errors[i].name_index          = name_index;
  2012.     errors[i].num                 = i;
  2013.     errors[i].left_token          = (left_token > Loc(right_token) ? Loc(right_token) : left_token);
  2014.     errors[i].right_token         = Loc(right_token);
  2015.     errors[i].right_string_length = lex_stream -> NameLength(right_token);
  2016.     errors[i].scope_name_index    = scope_name_index;
  2017.  
  2018.     if (control.option.dump_errors)
  2019.     {
  2020.         if (errors[i].left_token < errors[i].right_token)
  2021.              PrintSecondaryMessage(i);
  2022.         else PrintPrimaryMessage(i);
  2023.         errors.Reset(1); // we only need to indicate that at least one error was detected... See print_messages
  2024.         cout.flush();
  2025.     }
  2026.  
  2027.     return;
  2028. }
  2029.  
  2030.  
  2031. /*****************************************************************/
  2032. /* This procedure is invoked to print JIKES error messages that  */
  2033. /* have been stored in the array: error.                         */
  2034. /*****************************************************************/
  2035. void ParseError::PrintMessages()
  2036. {
  2037.     if (control.option.dump_errors || errors.Length() == 0)
  2038.     {
  2039.         cout.flush();
  2040.         return;
  2041.     }
  2042.  
  2043.     if (control.option.errors)
  2044.     {
  2045.         cout << "\nFound " << errors.Length() << " syntax error" << (errors.Length() == 1 ? "" : "s")
  2046.              << " in \"";
  2047.         Unicode::Cout(lex_stream -> FileName());
  2048.         cout << "\":";
  2049.  
  2050.         lex_stream -> RereadInput();
  2051.  
  2052.         if (! lex_stream -> InputBuffer())
  2053.         {
  2054.             char *file_name = lex_stream -> FileName();
  2055.             int length = lex_stream -> FileNameLength();
  2056.             wchar_t *name = new wchar_t[length + 1];
  2057.             for (int i = 0; i < length; i++)
  2058.                 name[i] = file_name[i];
  2059.             name[length] = U_NULL;
  2060.             control.system_semantic -> ReportSemError(SemanticError::CANNOT_REOPEN_FILE,
  2061.                                                       0,
  2062.                                                       0,
  2063.                                                       name);
  2064.             delete [] name;
  2065.             return;
  2066.         }
  2067.     }
  2068.     else if (! lex_stream -> ComputeColumns())
  2069.     {
  2070.         char *file_name = lex_stream -> FileName();
  2071.         int length = lex_stream -> FileNameLength();
  2072.         wchar_t *name = new wchar_t[length + 1];
  2073.         for (int i = 0; i < length; i++)
  2074.             name[i] = file_name[i];
  2075.         name[length] = U_NULL;
  2076.         control.system_semantic -> ReportSemError(SemanticError::CANNOT_COMPUTE_COLUMNS,
  2077.                                                   0,
  2078.                                                   0,
  2079.                                                   name);
  2080.         delete [] name;
  2081.     }
  2082.  
  2083.     SortMessages();
  2084.  
  2085.     int stack_top = -1;
  2086.     int *error_stack = new int[errors.Length()];
  2087.  
  2088.     for (int k = 0; k < errors.Length(); k++)
  2089.     {
  2090.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2091.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2092.             right_column_no = lex_stream -> Column(errors[k].right_token),
  2093.             msg_code        = errors[k].msg_code;
  2094.  
  2095.         Location left_token = errors[k].left_token;
  2096.  
  2097.         for (; stack_top >= 0 && (errors[error_stack[stack_top]].right_token <= left_token); stack_top--)
  2098.         {
  2099.              if (stack_top == 0)
  2100.                  PrintLargeMessage(error_stack[stack_top]);
  2101.              else
  2102.              {
  2103.                  int i = error_stack[stack_top],
  2104.                      j = error_stack[stack_top - 1];
  2105.  
  2106.                  if ((errors[i].msg_code != SECONDARY_CODE &&
  2107.                       errors[i].msg_code != MISPLACED_CODE &&
  2108.                       errors[i].msg_code != DELETION_CODE) ||
  2109.                      (errors[j].msg_code != DELETION_CODE  &&
  2110.                       errors[j].msg_code != MISPLACED_CODE &&
  2111.                       errors[j].msg_code != SECONDARY_CODE))
  2112.                      PrintLargeMessage(i);
  2113.              }
  2114.         }
  2115.  
  2116.         if (errors[k].left_token < errors[k].right_token)
  2117.         {
  2118.             stack_top++;
  2119.             error_stack[stack_top] = k;
  2120.         }
  2121.         else if ((stack_top >= 0) &&
  2122.                  (errors[error_stack[stack_top]].msg_code ==
  2123.                   SECONDARY_CODE ||
  2124.                   errors[error_stack[stack_top]].msg_code ==
  2125.                   DELETION_CODE) &&
  2126.                  (errors[k].left_token ==
  2127.                       errors[error_stack[stack_top]].left_token ||
  2128.                   errors[k].right_token ==
  2129.                       errors[error_stack[stack_top]].right_token));
  2130.         else /* NOTE that input_line already contains a '\n' character */
  2131.         {
  2132.             if (control.option.errors)
  2133.             {
  2134.                 int m = left_column_no,
  2135.                     n = right_column_no + errors[k].right_string_length - 1;
  2136.  
  2137.                 cout << "\n\n";
  2138.                 cout.width(6);
  2139.                 cout << left_line_no << ". ";
  2140.                 for (int i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  2141.                     Unicode::Cout(lex_stream -> InputBuffer()[i]);
  2142.  
  2143.                 if ((msg_code == SUBSTITUTION_CODE) ||
  2144.                     (n == m) ||
  2145.                     (msg_code == BEFORE_CODE)  ||
  2146.                     (msg_code == INVALID_CODE  && n <= (m+1)) ||
  2147.                     (msg_code == DELETION_CODE &&
  2148.                      left_column_no == right_column_no))
  2149.                 {
  2150.                     cout.width(left_column_no + 9);
  2151.                     cout << "^\n";
  2152.                 }
  2153.                 else if (msg_code == INSERTION_CODE ||
  2154.                          msg_code == EOF_CODE)
  2155.                 {
  2156.                     cout.width(n + 9);
  2157.                     cout << "^\n";
  2158.                 }
  2159.                 else
  2160.                 {
  2161.                     cout.width(left_column_no + 8);
  2162.                     cout << "<";
  2163.                     cout.width(right_column_no + errors[k].right_string_length - left_column_no);
  2164.                     cout.fill('-');
  2165.                     cout << (msg_code == SCOPE_CODE || msg_code == MANUAL_CODE ? "^\n" : ">\n");
  2166.                     cout.fill(' ');
  2167.                 }
  2168.             }
  2169.  
  2170.             PrintPrimaryMessage(k);
  2171.         }
  2172.     }
  2173.  
  2174.     for (; stack_top > 0; stack_top--)
  2175.     {
  2176.         int i = error_stack[stack_top],
  2177.             j = error_stack[stack_top - 1];
  2178.  
  2179.         if ((errors[i].msg_code != SECONDARY_CODE &&
  2180.              errors[i].msg_code != DELETION_CODE) ||
  2181.             (errors[j].msg_code != DELETION_CODE  &&
  2182.              errors[j].msg_code != SECONDARY_CODE))
  2183.            PrintLargeMessage(i);
  2184.     }
  2185.     if (stack_top == 0)
  2186.         PrintLargeMessage(error_stack[stack_top]);
  2187.  
  2188.     cout.flush();
  2189.  
  2190.     delete [] error_stack;
  2191.  
  2192.     if (control.option.errors)
  2193.         lex_stream -> DestroyInput();
  2194.  
  2195.     return;
  2196. }
  2197.  
  2198.  
  2199. //
  2200. // This procedure is invoked to print a large message that may
  2201. // span more than one line. The parameter ptr points to the
  2202. // starting line. The parameter k points to the error message in
  2203. // the error structure.
  2204. //
  2205. void ParseError::PrintLargeMessage(int k)
  2206. {
  2207.     if (control.option.errors)
  2208.     {
  2209.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2210.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2211.             right_line_no   = lex_stream -> Line(errors[k].right_token),
  2212.             right_column_no = lex_stream -> Column(errors[k].right_token);
  2213.  
  2214.         if (left_line_no == right_line_no)
  2215.         {
  2216.             cout << "\n\n";
  2217.             cout.width(6);
  2218.             cout << left_line_no << ". ";
  2219.             for (int i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  2220.                 Unicode::Cout(lex_stream -> InputBuffer()[i]);
  2221.  
  2222.             cout.width(left_column_no + 8);
  2223.             cout << (errors[k].msg_code == SCOPE_CODE || errors[k].msg_code == MANUAL_CODE ? "^" : "<");
  2224.  
  2225.             cout.width(right_column_no + errors[k].right_string_length - left_column_no);
  2226.             cout.fill('-');
  2227.             cout << (errors[k].msg_code == SCOPE_CODE || errors[k].msg_code == MANUAL_CODE ? "^\n" : ">\n");
  2228.             cout.fill(' ');
  2229.         }
  2230.         else
  2231.         {
  2232.             cout << "\n\n";
  2233.             cout.width(left_column_no + 8);
  2234.             cout << "<";
  2235.  
  2236.             cout.width(lex_stream -> LineSegmentLength(errors[k].left_token));
  2237.             cout.fill('-');
  2238.             cout << "\n";
  2239.             cout.fill(' ');
  2240.  
  2241.             cout.width(6);
  2242.             cout << left_line_no << ". ";
  2243.             int i;
  2244.             for (i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  2245.                 Unicode::Cout(lex_stream -> InputBuffer()[i]);
  2246.  
  2247.             if (right_line_no > left_line_no + 1)
  2248.             {
  2249.                 cout.width(left_column_no + 7);
  2250.                 cout << " ";
  2251.                 cout << ". . .\n";
  2252.             }
  2253.  
  2254.             cout.width(6);
  2255.             cout << right_line_no << ". ";
  2256.             for (i = lex_stream -> LineStart(right_line_no); i <= lex_stream -> LineEnd(right_line_no); i++)
  2257.                 Unicode::Cout(lex_stream -> InputBuffer()[i]);
  2258.  
  2259.             cout.width(8);
  2260.             cout << "";
  2261.             cout.width(right_column_no + errors[k].right_string_length);
  2262.             cout.fill('-');
  2263.             cout << (errors[k].msg_code == SCOPE_CODE || errors[k].msg_code == MANUAL_CODE ? "^\n" : ">\n");
  2264.             cout.fill(' ');
  2265.         }
  2266.     }
  2267.  
  2268.     PrintSecondaryMessage(k);
  2269.  
  2270.     return;
  2271. }
  2272.  
  2273. //
  2274. // This procedure is invoked to form a primary error message. The
  2275. // parameter k identifies the error to be processed.  The global
  2276. // variable: msg, is used to store the message.
  2277. //
  2278. void ParseError::PrintPrimaryMessage(int k)
  2279. {
  2280.     const char *name;
  2281.     int i,
  2282.         len = 0;
  2283.  
  2284. #if defined(FULL_DIAGNOSIS)
  2285.     if (errors[k].name_index >= 0)
  2286.     {
  2287.         len = name_length[errors[k].name_index];
  2288.         name = &string_buffer[name_start[errors[k].name_index]];
  2289.     }
  2290. #endif
  2291.  
  2292.     if (! control.option.errors)
  2293.     {
  2294.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2295.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2296.             right_line_no   = lex_stream -> Line(errors[k].right_token),
  2297.             right_column_no = lex_stream -> Column(errors[k].right_token);
  2298.  
  2299.         if (right_column_no != 0) // could not compute a column number
  2300.             right_column_no += (errors[k].right_string_length - 1); // point to last character in right token
  2301.  
  2302.         Unicode::Cout(lex_stream -> FileName());
  2303.         cout   << ':' << left_line_no  << ':' << left_column_no 
  2304.              << ':' << right_line_no << ':' << right_column_no
  2305.              << ":\n    Syntax: ";
  2306.     }
  2307.     else cout << "*** Syntax Error: ";
  2308.  
  2309.     switch(errors[k].msg_code)
  2310.     {
  2311.         case ERROR_CODE:
  2312.              cout << "Parsing terminated at this token";
  2313.              break;
  2314.         case BEFORE_CODE:
  2315.              for (i = 0; i < len; i++)
  2316.                  cout << name[i];
  2317.              cout << " inserted before this token";
  2318.              break;
  2319.         case INSERTION_CODE:
  2320.              for (i = 0; i < len; i++)
  2321.                  cout << name[i];
  2322.              cout << " expected after this token";
  2323.              break;
  2324.         case DELETION_CODE:
  2325.              if (errors[k].left_token == errors[k].right_token)
  2326.                   cout << "Unexpected symbol ignored";
  2327.              else cout << "Unexpected symbols ignored";
  2328.              break;
  2329.         case INVALID_CODE:
  2330.              if (len == 0)
  2331.                  cout << "Unexpected input discarded";
  2332.              else
  2333.              {
  2334.                  cout << "Invalid ";
  2335.                  for (i = 0; i < len; i++)
  2336.                      cout << name[i];
  2337.              }
  2338.              break;
  2339.         case SUBSTITUTION_CODE:
  2340.              for (i = 0; i < len; i++)
  2341.                  cout << name[i];
  2342.              cout << " expected instead of this token";
  2343.              break;
  2344. #if defined(SCOPE_REPAIR)
  2345.         case SCOPE_CODE:
  2346.              cout << '\"';
  2347.              for (i = scope_suffix[- (int) errors[k].name_index];
  2348.                   scope_rhs[i] != 0; i++)
  2349.              {
  2350.                  len  = name_length[scope_rhs[i]];
  2351.                  name = &string_buffer[name_start[scope_rhs[i]]];
  2352.                  for (int j = 0; j < len; j++)
  2353.                      cout << name[j];
  2354.                  if (scope_rhs[i+1]) // any more symbols to print?
  2355.                      cout << ' ';
  2356.              }
  2357.              cout << '\"';
  2358.              cout << " inserted to complete ";
  2359.              //
  2360.              // TODO: This should not be an option
  2361.              //
  2362.              if (errors[k].scope_name_index)
  2363.              {
  2364.                  len  = name_length[errors[k].scope_name_index];
  2365.                  name = &string_buffer[name_start[errors[k].scope_name_index]];
  2366.                  for (int j = 0; j < len; j++) // any more symbols to print?
  2367.                       cout << name[j];
  2368.              }
  2369.              else cout << "scope";
  2370.              break;
  2371. #endif
  2372.         case MANUAL_CODE:
  2373.              cout << '\"';
  2374.              for (i = 0; i < len; i++)
  2375.                  cout << name[i];
  2376.              cout << "\" inserted to complete structure";
  2377.              break;
  2378.         case MERGE_CODE:
  2379.              cout << "symbols merged to form ";
  2380.              for (i = 0; i < len; i++)
  2381.                  cout << name[i];
  2382.              break;
  2383.         case EOF_CODE:
  2384.              for (i = 0; i < len; i++)
  2385.                  cout << name[i];
  2386.              cout << " reached after this token";
  2387.              break;
  2388.         default:
  2389.              if (errors[k].msg_code == MISPLACED_CODE)
  2390.                   cout << "misplaced construct(s)";
  2391.              else if (len == 0)
  2392.                   cout << "unexpected input discarded";
  2393.              else
  2394.              {
  2395.                  for (i = 0; i < len; i++)
  2396.                      cout << name[i];
  2397.                  cout << " expected instead";
  2398.              }
  2399.              break;
  2400.     }
  2401.  
  2402.     cout << '\n';
  2403.  
  2404.     return;
  2405. }
  2406.  
  2407. //
  2408. // This procedure is invoked to form a secondary error message.
  2409. // The parameter k identifies the error to be processed.  The
  2410. // global variable: msg, is used to store the message.
  2411. //
  2412. void ParseError::PrintSecondaryMessage(int k)
  2413. {
  2414.     const char *name;
  2415.     int i,
  2416.         len = 0;
  2417.  
  2418. #if defined(FULL_DIAGNOSIS)
  2419.     if (errors[k].name_index >= 0)
  2420.     {
  2421.         len = name_length[errors[k].name_index];
  2422.         name = &string_buffer[name_start[errors[k].name_index]];
  2423.     }
  2424. #endif
  2425.  
  2426.     if (! control.option.errors)
  2427.     {
  2428.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2429.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2430.             right_line_no   = lex_stream -> Line(errors[k].right_token),
  2431.             right_column_no = lex_stream -> Column(errors[k].right_token);
  2432.  
  2433.         if (right_column_no != 0) // could not compute a column number
  2434.             right_column_no += (errors[k].right_string_length - 1); // point to last character in right token
  2435.  
  2436.         Unicode::Cout(lex_stream -> FileName());
  2437.         cout << ':' << left_line_no  << ':' << left_column_no 
  2438.              << ':' << right_line_no << ':' << right_column_no
  2439.              << ":\n    Syntax: ";
  2440.     }
  2441.     else cout << "*** Syntax Error: ";
  2442.  
  2443.     switch(errors[k].msg_code)
  2444.     {
  2445.         case MISPLACED_CODE:
  2446.             cout << "Misplaced construct(s)";
  2447.             break;
  2448. #if defined(SCOPE_REPAIR)
  2449.         case SCOPE_CODE:
  2450.             cout << '\"';
  2451.             for (i = scope_suffix[- (int) errors[k].name_index]; scope_rhs[i] != 0; i++)
  2452.             {
  2453.                 len  = name_length[scope_rhs[i]];
  2454.                 name = &string_buffer[name_start[scope_rhs[i]]];
  2455.                 for (int j = 0; j < len; j++) // any more symbols to print?
  2456.                      cout << name[j];
  2457.                 if (scope_rhs[i+1])
  2458.                     cout << ' ';
  2459.             }
  2460.             cout << "\" inserted to complete ";
  2461.             //
  2462.             // TODO: This should not be an option
  2463.             //
  2464.             if (errors[k].scope_name_index)
  2465.             {
  2466.                 len  = name_length[errors[k].scope_name_index];
  2467.                 name = &string_buffer[name_start[errors[k].scope_name_index]];
  2468.                 for (int j = 0; j < len; j++) // any more symbols to print?
  2469.                      cout << name[j];
  2470.             }
  2471.             else cout << "phrase";
  2472.             break;
  2473. #endif
  2474.         case  MANUAL_CODE:
  2475.             cout << '\"';
  2476.             for (i = 0; i < len; i++)
  2477.                 cout << name[i];
  2478.             cout << "\" inserted to complete structure";
  2479.             break;
  2480.         case MERGE_CODE:
  2481.             cout << "Symbols merged to form ";
  2482.             for (i = 0; i < len; i++)
  2483.                 cout << name[i];
  2484.             break;
  2485.         default:
  2486.             if (errors[k].msg_code == DELETION_CODE || len == 0)
  2487.                 cout << "Unexpected input discarded";
  2488.             else
  2489.             {
  2490.                 for (i = 0; i < len; i++)
  2491.                     cout << name[i];
  2492.                 cout << " expected instead";
  2493.             }
  2494.     }
  2495.  
  2496.     cout << '\n';
  2497.  
  2498.     return;
  2499. }
  2500.